package com.question.common.utils;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.question.business.menu.model.vo.MenuRouteVO;
import com.question.common.service.ITreeRecursion;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 树形结构递归类
 *
 * @author star
 * @since 2022/7/8
 */
@Slf4j
public class TreeUtil {

    /**
     * 树形结构处理
     *
     * @param data 所有数据
     * @return List<ITreeRecursion>
     */
    @NotNull
    public static <T extends ITreeRecursion<T>> List<T> handleTrees(@NotNull List<T> data, @NotNull Class<T> clazz) {
        List<T> list = new ArrayList<>();
        // 判断数据是否为空
        if (CollectionUtils.isNotEmpty(data)) {

            // 以parentKey为ID-初始化数据
            Map<String, List<T>> map = data.stream().collect(Collectors.groupingBy(ITreeRecursion::getId));

            // 以parentKey为ID-初始化数据
            Map<String, List<T>> parentMap = data.stream().collect(Collectors.groupingBy(ITreeRecursion::getParentId));

            // 获取顶级节点
            List<T> tops = new ArrayList<>();
            for (T tree : data) {
                if (Objects.isNull(map.get(tree.getParentId()))) {
                    tops.add(tree);
                }
            }
            // 处理顶级节点
            if (CollectionUtils.isNotEmpty(tops)) {
                for (T top : tops) {
                    if (Objects.nonNull(top)) {
                        T bean = recursion(top, clazz, parentMap);
                        list.add(bean);
                    }
                }
            }
        } else {
            log.warn("递归集合为空");
        }
        return list;
    }

    /**
     * 递归节点
     *
     * @param node      当前节点
     * @param parentMap 所有节点
     */
    @NotNull
    private static <T extends ITreeRecursion<T>> T recursion(@NotNull T node, @NotNull Class<T> clazz, @NotNull Map<String, List<T>> parentMap) {
        T bean = clone(node, clazz);
        List<T> childNodes = parentMap.get(node.getId());
        // 判断是否需要递归
        if (CollectionUtils.isNotEmpty(childNodes)) {
            List<T> list = new ArrayList<>(childNodes.size());
            for (T childNode : childNodes) {
                if (Objects.nonNull(childNode)) {
                    list.add(recursion(childNode, clazz, parentMap));
                }
            }
            bean.setChildren(list);
        }
        return bean;
    }

    /**
     * 树形结构处理
     *
     * @param data 所有数据
     * @return List<MenuRouteVO>
     */
    @NotNull
    public static List<MenuRouteVO> handleMenuTrees(@NotNull List<MenuRouteVO> data) {
        List<MenuRouteVO> list = new ArrayList<>();
        // 判断数据是否为空
        if (CollectionUtils.isNotEmpty(data)) {

            // 以parentKey为ID-初始化数据
            Map<String, List<MenuRouteVO>> map = data.stream().collect(Collectors.groupingBy(MenuRouteVO::getId));

            // 以parentKey为ID-初始化数据
            Map<String, List<MenuRouteVO>> parentMap = data.stream().collect(Collectors.groupingBy(MenuRouteVO::getParentId));

            // 获取顶级节点
            List<MenuRouteVO> tops = new ArrayList<>();
            for (MenuRouteVO tree : data) {
                if (Objects.isNull(map.get(tree.getParentId()))) {
                    tops.add(tree);
                }
            }
            tops.sort(Comparator.comparing(MenuRouteVO::getMenuOrder));
            // 处理顶级节点
            if (CollectionUtils.isNotEmpty(tops)) {
                for (MenuRouteVO top : tops) {
                    if (Objects.nonNull(top)) {
                        MenuRouteVO bean = recursionMenu(top, parentMap);
                        list.add(bean);
                    }
                }
            }
        } else {
            log.warn("递归集合为空");
        }
        return list;
    }

    /**
     * 递归节点
     *
     * @param node      当前节点
     * @param parentMap 所有节点
     */
    @NotNull
    private static MenuRouteVO recursionMenu(@NotNull MenuRouteVO node, @NotNull Map<String, List<MenuRouteVO>> parentMap) {
        MenuRouteVO bean = new MenuRouteVO();
        BeanUtils.copyProperties(node, bean);
        List<MenuRouteVO> childNodes = parentMap.get(node.getId());
        // 判断是否需要递归
        if (CollectionUtils.isNotEmpty(childNodes)) {
            List<MenuRouteVO> list = new ArrayList<>(childNodes.size());
            for (MenuRouteVO childNode : childNodes) {
                if (Objects.nonNull(childNode)) {
                    list.add(recursionMenu(childNode, parentMap));
                }
            }
            list.sort(Comparator.comparing(MenuRouteVO::getMenuOrder));
            bean.setRoutes(list);
        }
        return bean;
    }

    /**
     * 复制对象到指定类
     *
     * @param object 源
     * @param clazz  目标类
     * @param <T>    泛型
     * @return 返回数据
     */
    @NotNull
    private static <T> T clone(@NotNull Object object, @NotNull Class<T> clazz) {
        String json = JSON.toJSONString(object);
        return JSON.parseObject(json, clazz);
    }

}
